package simulator;
import java.util.*;

/**
 * @deprecated
 * This class generates mazes
 * ('maze' in this case refers to an instance of Environment containing walls 
 * configured according to the rules of IARoC)
 * @author morris
 * This doesn't work, and has been replaced by the Visual Maze Builder tool
 */

public class MazeFactory {
	public static final int wallwidth = 10;
	
	/**
	 * generates a maze with specified width and height
	 * hopefully width and height are both multiples of wallwidth, otherwise difficulty ensues
	 * implements a depth-first recursive backtracking algorithm
	 * (see http://en.wikipedia.org/wiki/Maze_generation_algorithm)
	 * @param width desired width of maze
	 * @param height desired height of maze
	 * @return a randomly generated maze of width and height
	 */
	public static Environment generateMaze(int width, int height) {
		Environment maze = new Environment();
		
		int cellsx = width / wallwidth;
		int cellsy = height / wallwidth;
		
		boolean[][] visited = new boolean[cellsx][cellsy]; //has a boolean for each cell
		boolean[][] horizwalls = new boolean[cellsx][cellsy + 1]; //should a particular cell NOT have a wall?
		boolean[][] vertwalls = new boolean[cellsx + 1][cellsy]; //note: defaults to false
		
		int[] coords = {(int)(Math.random() * cellsx), 0}; //coordinates to start at
		Stack<int[]> cellstack = new Stack<int[]>();
		cellstack.push(coords);
		recurse(cellstack, visited, horizwalls, vertwalls, cellsx, cellsy);
		
		boolean onwall = false; //still measuring contiguous blocks of wall?
		int wallstart = -1;
		int wallend = -1;
		
		for(int i = 0; i < horizwalls.length; i++) { //go through each row of horizontal walls
			for(int j = 0; j < horizwalls[0].length; j++) {
				if(!horizwalls[i][j]) {
					if(!onwall)
						wallstart = j;
					wallend = j;
					onwall = true;
				}else{
					if(onwall)
						maze.add(new Wall(wallstart * wallwidth, i * wallwidth, wallend * wallwidth, (i + 1) * wallwidth));
					onwall = false;
				}
			}
		}
		
		onwall = false;
		wallstart = -1;
		wallend = -1;
		for(int i = 0; i < vertwalls[0].length; i++) { //go through each col of vertical walls
			for(int j = 0; j < vertwalls.length; j++) {
				if(!vertwalls[j][i]) {
					if(!onwall)
						wallstart = j;
					wallend = j;
					onwall = true;
				}else{
					if(onwall)
						maze.add(new Wall(i * wallwidth, wallstart * wallwidth, (i + 1) * wallwidth, wallend * wallwidth));
					onwall = false;
				}	
			}
		}
		return maze;
	}
	
	private static ArrayList<int[]> getNeighbors(int[] curcell, boolean[][] visited, int cellsx, int cellsy) {
		ArrayList<int[]> neighbors = new ArrayList<int[]>();
		for(int i = -1; i <= 1; i++)
			for(int j = -1; j <= 1; j++) //visit all neighbors
				if((i == 0) ^ (j == 0)) {
					int x = curcell[0] + i;
					if(x >= 0 && x < cellsx) { //check to see if neighbor exists
						int y = curcell[1] + j;
						if(y >= 0 && y < cellsy
								&& !visited[x][y]) { //...and hasn't been visited
							int[] coords = {x, y};
							neighbors.add(coords); //if so, add to ArrayList neighbors
						}
					}
				}
		return neighbors;
	}
	
	private static void recurse(Stack<int[]> cellstack, boolean[][] visited,
			boolean[][] horizwalls, boolean[][] vertwalls, int cellsx, int cellsy) {
		if(!cellstack.isEmpty()) {
			int[] curcell = cellstack.peek(); //get the current cell
			visited[curcell[0]][curcell[1]] = true; //it's been visited now
			
			ArrayList<int[]> neighbors = getNeighbors(curcell, visited, cellsx, cellsy);
			
			if(!neighbors.isEmpty()) {
				while(!neighbors.isEmpty()) { //time for recursion!
					//do it to neighbors till none haven't been visited
					int[] newcell = neighbors.remove((int)(Math.random() * neighbors.size()));
					cellstack.add(newcell);
					int xof = curcell[0] - newcell[0]; //x + y offsets
					int yof = curcell[1] - newcell[1];
					if(xof != 0) { //remove the wall bw/ the two cells
						vertwalls[curcell[0]][curcell[1]] = true;
					}else{
						horizwalls[curcell[0]][curcell[1]] = true;
					}
					recurse(cellstack, visited, horizwalls, vertwalls, cellsx, cellsy);
				}
			}else{
				cellstack.pop();
			}
		}
	}
}
